package com.gitee.wsl.mathematics.statistics

import kotlin.math.exp
import kotlin.math.pow
import kotlin.math.sqrt


abstract class Frequency {
    //统计频数
    fun average(vararg m: Float): Float { //计算平均值
        val len = m.size
        var allNub = 0f
        for (i in 0 until len) {
            allNub += m[i]
        }
        allNub /= len
        return allNub
    }

    fun averageByList(m: List<Float>): Float { //计算平均值
        val len = m.size
        var allNub = 0f
        for (i in 0 until len) {
            allNub += m[i]
        }
        allNub = (allNub/ len)
        return allNub
    }

    fun sigma(vararg m: Float): Float { //求和
        val len = m.size
        var allNub = 0f
        for (i in 0 until len) {
            allNub += m[i]
        }
        return allNub
    }

    fun getPointLength(x: Float, y: Float, i: Float, j: Float): Float { //获取两个二维坐标之间的欧式距离
        return sqrt((x- i).pow(2.0f) + (y- j).pow(2.0f))
    }

    fun variance(vararg m: Float): Float { //计算方差
        val ave = average(*m) //先计算出平均值
        var allNub = 0f
        for (i in m.indices) {
            allNub += (m[i] - ave).pow(2.0f)
        }
        return allNub / m.size
    }

    fun varianceByAve(m: FloatArray, ave: Float): Float { // 计算方差，依赖平均值
        var allNub = 0f
        for (i in m.indices) {
            allNub += (m[i] - ave).pow(2.0f)
        }
        return allNub / m.size
    }

    fun sdByAvg(m: FloatArray, avg: Float): Float { //计算标准差，带平均值
        val `var` = varianceByAve(m, avg)
        return sqrt(`var`)
    }

    fun sd(vararg m: Float): Float { //计算标准差
        val `var` = variance(*m)
        return sqrt(`var`)
    }

    fun dcByAvg(m: FloatArray, ave: Float): Float { //带均值算离散
        var allNub = 0f
        for (i in m.indices) {
            allNub += (m[i] - ave).pow(2.0f)
        }
        return (sqrt((allNub/m.size)) /ave) //离散系数
    }

    fun dc(vararg m: Float): Float { //计算离散系数
        val ave = average(*m) //先计算出平均值
        var dc = 0f
        if (ave > 0) {
            var allNub = 0f
            for (i in m.indices) {
                allNub += (m[i] - ave).pow(2.0f)
            }
            dc = sqrt(allNub/ m.size) / ave //离散系数
        }
        return dc
    }

    fun softMax(t: Int, vararg m: Float): Float { //下标和数组
        val my = exp(m[t].toDouble()) as Float
        var all = 0.0f
        val allLength = m.size
        for (i in 0 until allLength) {
            all += exp(m[i].toDouble()) as Float
        }
        return my/all
    }

    fun getLimit(m: FloatArray): FloatArray { //获取数组中的最大值和最小值，最小值在前，最大值在后
        val limit = FloatArray(2)
        var max = 0f
        var min = -1f
        val l = m.size
        for (i in 0 until l) {
            val nub = m[i]
            if (min == -1f || nub < min) {
                min = nub
            }
            if (nub > max) {
                max = nub
            }
        }
        limit[0] = min
        limit[1] = max
        return limit
    }

    companion object {
        fun getEDist(x1: FloatArray, x2: FloatArray): Float { //返回两个等长数组之间的欧式距离
            val y = FloatArray(x1.size)
            for (i in y.indices) {
                y[i] = x1[i] - x2[i]
            }
            var sigma = 0f
            for (i in y.indices) {
                sigma += y[i].pow(2.0f)
            }
            return sqrt(sigma)
        }
    }
}